package com.shloma.bbts.controller;

import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.shloma.bbts.config.FXMLPage;
import com.shloma.bbts.controller.support.AbstractSubPageController;
import com.shloma.bbts.controller.support.CheckBoxButtonTableCell;
import com.shloma.bbts.controller.support.EditingCell;
import com.shloma.bbts.controller.support.SeqNoTableCell;
import com.shloma.bbts.entity.AreaAcct;
import com.shloma.bbts.entity.SysConfig;
import com.shloma.bbts.service.AreaAcctService;
import com.shloma.bbts.service.SysConfigService;
import com.shloma.bbts.utils.AlertUtil;
import com.shloma.bbts.utils.BeanFactoryUtils;
import com.shloma.bbts.utils.FormCheckUtils;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;

/**
 * Description: TODO(这里用一句话描述这个类的作用)
 * <p>
 *
 * @author xuefeng.shi
 * @date 2018/12/07
 * @version v1.0.0
 */
public class ConfigManagerController extends AbstractSubPageController {

	private static Logger logger = LoggerFactory.getLogger(ConfigManagerController.class);

	@FXML
	private TextField primaryKey;
	@FXML
	private TextField corpServerPort;
	@FXML
	private TextField bankServerPort;
	@FXML
	private TextField corpIp;
	@FXML
	private TextField corpPort;
	@FXML
	private ChoiceBox<String> corpPkgEncode;
	@FXML
	private TextField bankIp;
	@FXML
	private TextField bankPort;
	@FXML
	private Button finalComfirm;
	@FXML
	private Button cancel;

	@FXML
	private TextField mainAcct;
	@FXML
	private ChoiceBox<AreaAcct> rgnCde;
	@FXML
	private Button queryAcct;
	@FXML
	private Button addAcct;
	@FXML
	private Button updateAcct;

	@FXML
	private TableView<AreaAcct> areaAcctList;
	private ObservableList<AreaAcct> observableAreaAcctList = FXCollections.observableArrayList();
	@FXML
	private TableColumn<AreaAcct, Boolean> isCheck;
	@FXML
	private TableColumn<AreaAcct, String> seqNoColumn;
	@FXML
	private TableColumn<AreaAcct, String> mainAcctColumn;
	@FXML
	private TableColumn<AreaAcct, String> mainAcctNmeColumn;
	@FXML
	private TableColumn<AreaAcct, String> rgnCdeColumn;
	@FXML
	private TableColumn<AreaAcct, String> rgnNmeColumn;

	private SysConfigService configService;
	private AreaAcctService acctService;

	/**
	 * 保存通讯参数
	 */
	@FXML
	public void saveSysConfig() {
		logger.info("保存参数");

		SysConfig saveSysCOnfig = new SysConfig();
		saveSysCOnfig.setId(primaryKey.getText());

		saveSysCOnfig.setCorpServerPort(Integer.valueOf(corpServerPort.getText()));
		saveSysCOnfig.setBankServerPort(Integer.valueOf(bankServerPort.getText()));
		saveSysCOnfig.setCorpIp(corpIp.getText());
		saveSysCOnfig.setCorpPort(Integer.valueOf(corpPort.getText()));
		saveSysCOnfig.setCorpPkgEncode(corpPkgEncode.getValue());
		saveSysCOnfig.setBankIp(bankIp.getText());
		saveSysCOnfig.setBankPort(Integer.valueOf(bankPort.getText()));
		configService.saveSysConfig(saveSysCOnfig);

		logger.info("保存参数配置并退出");
		Stage stage = (Stage) finalComfirm.getScene().getWindow();
		stage.close();

		AlertUtil.showInfoAlert("参数配置", "参数修改成功, 请求重启服务");
	}

	/**
	 * 退出参数配置界面
	 */
	@FXML
	public void exitConfigPage() {
		logger.info("参数配置界面退出");
		Stage stage = (Stage) cancel.getScene().getWindow();
		stage.close();
	}

	/**
	 * 查询主账号信息
	 */
	@FXML
	public void queryAccts() {
		logger.info("查询行政区划账户列表");

		AreaAcct queryAreaAcct = new AreaAcct();
		String querMainAcct = mainAcct.getText();
		queryAreaAcct.setMainAcct(querMainAcct);
		String queryRgnCde = rgnCde.getValue().getRgnCde();
		queryAreaAcct.setRgnCde(queryRgnCde);
		List<AreaAcct> queryResult = acctService.getAreaAcctsByQueryCondition(queryAreaAcct);

		observableAreaAcctList.setAll(queryResult);
		// observableAreaAcctList.addAll(queryResult);
	}

	@FXML
	public void delAreaAccts() {
		boolean hasCheck = hasCheck();
		if (!hasCheck) {
			AlertUtil.showWarnAlert("删除操作", "请选择需要删除的行政区划信息！");
			return;
		}

		Alert confirmationAlert = AlertUtil.showConfirmationAlert("确认信息", "确认删除选中的所以行政区划信息?");

		Optional<ButtonType> _buttonType = confirmationAlert.showAndWait();
		// 根据点击结果返回
		if (_buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)) {
			logger.info(">>>>> 用户确定删除行政区划操作");
			Iterator<AreaAcct> iterator = observableAreaAcctList.iterator();
			while (iterator.hasNext()) {
				AreaAcct current = iterator.next();
				if (current.getIsCheck()) {
					logger.info(">>>> will be deleted by rgnCde:{}", current.getRgnCde());
					acctService.deleteSelectedItem(current);
				}
			}

			// 刷新界面
			queryAccts();

			// 初始化下拉框
			initRgnCdeChoiceBox();
		} else {
			logger.info(">>>>> 用户取消删除行政区划操作");
		}
	}

	@FXML
	public void showAddAcctWindow() throws Exception {
		AddAreaAcctController controller = (AddAreaAcctController) loadFXMLPage(FXMLPage.ADD_AREA_ACCT_PAGE, false);
		controller.setMainUIController((MainUIController) this.getParentController());
		controller.setParentController(this);
		controller.showDialogStage();
	}

	@FXML
	public void updateAreaAccts() {
		boolean hasCheck = hasCheck();
		if (!hasCheck) {
			AlertUtil.showWarnAlert("修改操作", "请选择需要修改的行政区划信息！");
			return;
		}

		Alert confirmationAlert = AlertUtil.showConfirmationAlert("确认信息", "确认修改选中的所以行政区划信息?");

		Optional<ButtonType> _buttonType = confirmationAlert.showAndWait();
		// 根据点击结果返回
		if (_buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)) {
			logger.info(">>>>> 用户确定修改行政区划操作");
			Iterator<AreaAcct> iterator = observableAreaAcctList.iterator();
			while (iterator.hasNext()) {
				AreaAcct current = iterator.next();
				if (current.getIsCheck()) {
					logger.info(">>>> will be updated by rgnCde:{}", current.getRgnCde());
					acctService.updateSelectedItem(current);
				}
			}

			// 刷新界面
			queryAccts();

			// 初始化下拉框
			initRgnCdeChoiceBox();
		} else {
			logger.info(">>>>> 用户取消修改行政区划操作");
		}
	}

	/**
	 * @return
	 */
	private boolean hasCheck() {
		Iterator<AreaAcct> iterator = observableAreaAcctList.iterator();
		boolean hasCheck = false;
		while (iterator.hasNext()) {
			AreaAcct current = iterator.next();
			if (current.getIsCheck()) {
				hasCheck = true;
				break;
			}
		}
		return hasCheck;
	}

	/**
	 * 初始化行政区划下拉框
	 */
	public void initRgnCdeChoiceBox() {
		List<AreaAcct> accts = acctService.getAreaAccts();
		Map<String, String> rgnCdes = new HashMap<>();
		for (AreaAcct areaAcct : accts) {
			rgnCdes.put(areaAcct.getRgnCde(), areaAcct.getRgnNme());
		}
		rgnCde.setItems(FXCollections.observableArrayList(accts));

		// 设置默认选项
		AreaAcct element = new AreaAcct();
		element.setRgnNme("-请选择-");
		rgnCde.getItems().add(0, element);
		rgnCde.setValue(element);
	}

	/**
	 * 初始化界面
	 * 
	 * @see javafx.fxml.Initializable#initialize(java.net.URL,
	 *      java.util.ResourceBundle)
	 */
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		// 初始化下拉框
		corpPkgEncode.setItems(FXCollections.observableArrayList("GBK", "UTF-8"));

		configService = BeanFactoryUtils.getBean(SysConfigService.class);
		acctService = BeanFactoryUtils.getBean(AreaAcctService.class);

		// 通讯参数初始化
		SysConfig querySysConfig = configService.querySysConfig();
		primaryKey.setText(querySysConfig.getId());
		corpServerPort.setText(String.valueOf(querySysConfig.getCorpServerPort()));
		bankServerPort.setText(String.valueOf(querySysConfig.getBankServerPort()));
		corpIp.setText(querySysConfig.getCorpIp());
		corpPort.setText(String.valueOf(querySysConfig.getCorpPort()));
		corpPkgEncode.setValue(querySysConfig.getCorpPkgEncode());
		bankIp.setText(querySysConfig.getBankIp());
		bankPort.setText(String.valueOf(querySysConfig.getBankPort()));

		// 区划代码初始化
		rgnCde.converterProperty().set(new StringConverter<AreaAcct>() {
			@Override
			public String toString(AreaAcct object) {
				return object.getRgnNme();
			}

			@Override
			public AreaAcct fromString(String string) {
				return null;
			}
		});
		initRgnCdeChoiceBox();

		rgnCde.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
			if (oldValue != null && newValue != null) {
				logger.info(">>>> oldValue:{}", oldValue.getRgnNme());
				logger.info(">>>> newValue:{}", newValue.getRgnNme());
			}
		});

		// 通讯参数校验
		corpServerPort.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkPort(newValue)) {
				corpServerPort.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确端口号");
			}
		});
		bankServerPort.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkPort(newValue)) {
				bankServerPort.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确端口号");
			}
		});
		corpPort.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkPort(newValue)) {
				corpPort.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确端口号");
			}
		});
		bankPort.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkPort(newValue)) {
				bankPort.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确端口号");
			}
		});
		bankIp.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkIpAddress(newValue)) {
				bankIp.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确IP地址");
			}
		});
		corpIp.textProperty().addListener((observable, oldValue, newValue) -> {
			if (!FormCheckUtils.checkIpAddress(newValue)) {
				corpIp.setText(oldValue);
				AlertUtil.showWarnAlert("参数配置", "请输入正确IP地址");
			}
		});

		seqNoColumn.setCellFactory(new Callback<TableColumn<AreaAcct, String>, TableCell<AreaAcct, String>>() {
			@Override
			public TableCell<AreaAcct, String> call(TableColumn<AreaAcct, String> param) {
				SeqNoTableCell<AreaAcct, String> cell = new SeqNoTableCell<>();
				return cell;
			}
		});

		mainAcctColumn.setCellFactory((TableColumn<AreaAcct, String> p) -> new EditingCell<AreaAcct>());
		mainAcctNmeColumn.setCellFactory((TableColumn<AreaAcct, String> p) -> new EditingCell<AreaAcct>());
		rgnNmeColumn.setCellFactory((TableColumn<AreaAcct, String> p) -> new EditingCell<AreaAcct>());

		mainAcctColumn.setCellFactory(new Callback<TableColumn<AreaAcct, String>, TableCell<AreaAcct, String>>() {

			@Override
			public TableCell<AreaAcct, String> call(TableColumn<AreaAcct, String> param) {
				EditingCell<AreaAcct> editingCell = new EditingCell<AreaAcct>();
				TextField textField = (TextField) editingCell.getGraphic();
				if (null != textField) {
					textField.focusedProperty().addListener((ob, old, now) -> {
						if (!now) {

							AreaAcct areaAcct = observableAreaAcctList.get(editingCell.getIndex());
							logger.info("----------------------" + textField.getText());
							areaAcct.setMainAcct(textField.getText());
						}
					});
				}
				return editingCell;
			}
		});

		// 初始化表格
		mainAcctColumn.setCellValueFactory(new PropertyValueFactory<AreaAcct, String>("mainAcct"));
		mainAcctNmeColumn.setCellValueFactory(new PropertyValueFactory<AreaAcct, String>("mainAcctNme"));
		rgnCdeColumn.setCellValueFactory(new PropertyValueFactory<AreaAcct, String>("rgnCde"));
		rgnNmeColumn.setCellValueFactory(new PropertyValueFactory<AreaAcct, String>("rgnNme"));
		isCheck.setCellValueFactory(new PropertyValueFactory<AreaAcct, Boolean>("isCheck"));
		isCheck.setCellFactory(new Callback<TableColumn<AreaAcct, Boolean>, TableCell<AreaAcct, Boolean>>() {
			public TableCell<AreaAcct, Boolean> call(TableColumn<AreaAcct, Boolean> param) {
				final CheckBoxButtonTableCell<AreaAcct, Boolean> cell = new CheckBoxButtonTableCell<>();
				final CheckBox checkbox = (CheckBox) cell.getGraphic();
				checkbox.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {
						AreaAcct areaAcct = observableAreaAcctList.get(cell.getIndex());
						// if (areaAcct.getIsCheck()) {
						// areaAcct.setIsCheck(false);
						// } else {
						// areaAcct.setIsCheck(true);
						// }
						areaAcct.setIsCheck(!areaAcct.getIsCheck());

					}
				});
				return cell;
			}
		});
		
		areaAcctList.setItems(observableAreaAcctList);
	}
}
